
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>

#include "rstatd.h"
#include "server.h"

static rp_thread_t tid_hb = 0;		// TODO: Should we move this into <rstatd.h>?

//* Function: rp_rstatd_server_init()
//*  	To initialize a rstatd server
//*
Err rp_rstatd_server_init(int argc, char *argv[])
{
	char fname[] = "rp_rstatd_server_init";
	char msg[] = "fatal error";
	Err err;

	err = rp_log_init();	// TODO:
	
	err = rp_getopt_rstatd(argc, argv);
	err = rp_getcfg_rstatd();
	err = rp_daemonize();
		
	err = rp_ptable_init(&g_ptable_rstatd);
	err = rp_cqueue_init(&g_cqueue_rstatd_cmd, g_qlength_rstatd_cmd);
	err = rp_rstatd_scoreboard_init(&g_scoreboard_rstatd);

	/*	prefork rpointd and save the pid/state in the scoreboard 	*/
	
	char fpath[MAX_FILENAME_LENGTH];
	Snode *snode;
	int i;
	for (i=0; i<g_threshold_rstatd_min; i++)
	{
		snode = (Snode*)malloc(sizeof(Snode));
		
		if ((snode->pid = rp_process_create("rpointd", NULL)) <= 0)
		{
			free(snode);
			rp_log(LOG_CRITICAL, fname, "Fail to create new rpointd process");
			continue;
		} 
		
		sprintf(fpath, "/tmp/rally/%d", snode->pid);
		if ((snode->fd = open(fpath, O_RDWR | O_CREAT | O_SYNC)) < 0) 	// Rstatd is rsponsible for create/delete the score file		
		{
			err = rp_process_terminate(snode->pid, SIGTERM);		// Forceful kill the new rpointd process
			/*	pid 	= xxx
		 	*	fd   	= 0
		 	*	state= 0
		 	*/
			err = rp_ptable_put(&g_ptable_rstatd, (Pnode*)snode);
			rp_log(LOG_CRITICAL, fname, "Cannot open file under /tmp/rally");
			continue;
		} 
		
		if (mmap(snode->score, sizeof(Score), PROT_READ|PROT_WRITE, 
		          MAP_SHARED|MAP_LOCKED, snode->fd, 0) == MAP_FAILED)
		{
			close(snode->fd);
			err = rp_process_terminate(snode->pid, SIGTERM);		// Forceful kill the new rpointd process
			/*	pid 	= xxx
		 	*	fd   	= xxx
		 	*	state= 0
		 	*/	
			err = rp_ptable_put(&g_ptable_rstatd, (Pnode*)snode);
			rp_log(LOG_CRITICAL, fname, "Failed mmap file under /tmp/rally");
			continue;
		} 
		/*	pid 	= xxx
		 *	fd   	= xxx
		 *	state= SS_IDLE
		 */	
		snode->score->state= SS_IDLE;
		err = rp_rstatd_scoreboard_append(&g_scoreboard_rstatd, snode);
	}
	
	err = rp_thread_create(&tid_hb, rp_rstatd_hb, NULL);
	
	return err;
}

Err rp_rstatd_server_run()
{
	char fname[] = "rp_rstatd_server_run";
	char msg[] = "fatal error";
	Err err;
	Cmd* pCmd;
 
	err = rp_thread_run(&g_cond_rstatd_hb);

	err = rp_rstatd_manager();

	return err;
}

Err rp_rstatd_server_finalize()
{
	char fname[] = "rp_rstatd_server_finalize";
	char msg[] = "fatal error";
	Err err;
	
	err = rp_cqueue_finalize(&g_cqueue_rstatd_cmd);
	err = rp_rstatd_scoreboard_finalize(&g_scoreboard_rstatd);
	err = rp_ptable_finalize(&g_ptable_rstatd);
	err = rp_log_finalize();

	return err;
}

int main(int argc, char *argv[])
{
	Err err;

	err = rp_rstatd_server_init(argc, argv);
	err = rp_rstatd_server_run();	
	err = rp_rstatd_server_finalize();
	
	exit(0);
}


